/**
 * Labox有限公司项目InnovationServer
 * Labox版权所有 @copyright 2010
 * @javaclass Engine.java @author 丁宁 @time 2010-2-1
 */
package labox.innovation.gameserver;

import javolution.util.FastMap;
import javolution.util.FastMap.Entry;
import java.util.concurrent.ConcurrentLinkedQueue;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import labox.innovation.config.Config;
import labox.innovation.gameserver.ai.CtrlEvent;
import labox.innovation.gameserver.model.FuzeWorld;
import labox.innovation.gameserver.model.actor.L2Character;
import labox.innovation.gameserver.model.actor.instance.FuzePcInstance;
import labox.innovation.gameserver.network.L2GameClient;
import labox.innovation.gameserver.timer.TimerController;
import labox.innovation.netcore.ReceivablePacket;

/**
 * 游戏主引擎类，游戏所有逻辑功能的核心驱动
 * 
 */
public final class Engine extends Thread {

	private static final Logger _log = LoggerFactory.getLogger(Engine.class.getName());

	private volatile boolean _run;

	private static final int TIME_PER_FRAME = 100;

	private ConcurrentLinkedQueue<Runnable> _critical = new ConcurrentLinkedQueue<Runnable>();

	public static Engine getInstance() {
		return SingletonHolder._instance;
	}

	private Engine() {
		_run = true;
		setName("MAIN LOGIC THREAD");
		setPriority(MAX_PRIORITY);
	}

	public void run() {
		FastMap<Long, FuzePcInstance> players = FuzeWorld.getInstance().getAllPlayers();
		FastMap<Long, L2Character> charactors = FuzeWorld.getInstance().getAllCharacters();
		long interval;
		long framStartTime = System.currentTimeMillis();
		ReceivablePacket<L2GameClient> pak;
		ConcurrentLinkedQueue<Runnable> crit = _critical;
		Runnable task;
		FuzePcInstance player;
		L2Character _char;
		Entry<Long, FuzePcInstance> e;
		Entry<Long, FuzePcInstance> n;

		Entry<Long, L2Character> e1;
		Entry<Long, L2Character> n1;

		while (_run) {
			try {
				while ((task = crit.poll()) != null) {
					try {
						task.run();
					} catch (Exception ex) {
						_log.error("main logic thread task error", Config.SERVER_ID, ex);
					}
				}
				e = players.head().getNext();
				n = players.tail();

				for (; e != n;) {//处理客户端提交的数据包
					player = e.getValue();
					e = e.getNext();
					pak = player.getClient().getPacke();
					if (pak == null)
						continue;
					pak.run();
				}

				TimerController.getInstance().run();//定时器处理

				interval = System.currentTimeMillis() - framStartTime;

				if (interval >= 150L) {
					System.out.println("Engine Thread delay: " + interval + "ms.happen time:" + GameTimeController.getInstance().getNowDate());
				}

				if (interval > TIME_PER_FRAME) {
					framStartTime += TIME_PER_FRAME;//curFrameTime=System.currentTimeMillis()-(interval-TIME_PER_FRAME);

					e1 = charactors.head().getNext();
					n1 = charactors.tail();

					for (; e1 != n1;) {//处理所有角色对象的AI
						_char = e1.getValue();
						e1 = e1.getNext();
						if (_char.hasAI() && !_char.isCoreAIDisabled()) {
							try {
								_char.getAI().notifyEvent(CtrlEvent.EVT_THINK, null, null);
							} catch (Exception ex) {
								_log.error("Character AI invoke error", _char.getObjectId(), ex);
							}
						}
					}
				} else
					Thread.yield();
			} catch (Exception ex) {
				ex.printStackTrace();
				_log.error("MAIN LOGIC THREAD ERROR!!!!", Config.SERVER_ID, ex);
			}

		}
	}

	public void close() {
		_run = false;
	}

	public boolean isClose() {
		return _run == false;
	}

	public void addTask(Runnable task) {
		_critical.offer(task);
	}

	@SuppressWarnings("synthetic-access")
	private static class SingletonHolder {
		protected static final Engine _instance = new Engine();
	}
}
